<?php
/**
 * UleAPI
 * 
 * @package UleAPI
 * @author David.Zhu <David909@21cn.com>
 * @version 1.0.0
 * @access public
 */
class UleRequest {
    var $mConfig;
    
    /**
     * UleAPI::__construct()
     * 
     * @return
     */
    function __construct($config) {
        $this->url = $config['host_url'];
        $this->appkey = $config['app_key'];
        $this->version_no = $config['app_version'];
        $this->return_type = $config['return_type'];
        $this->key = $config['key'];
    }
    /**
     * 
     * 
     * @param mixed $rHost
     * @param mixed $rPost
     * @param mixed $rData
     * @return
     */
    public function post($func, $rData) {
    	$sign = $this->uleEncryption($rData);
		$rData['sign'] = $sign;
		
        $flag = 0;
        $params = '';
        $argv = $rData;
        foreach ( $argv as $key => $value ) {
            if ($flag != 0) {
                $params .= "&";
                $flag = 1;
            }
            $params .= $key . "=";
            $params .= urlencode ( $value );
            $flag = 1;
        }
        $length = strlen ( $params );
       
        $fp = fsockopen ( $this->url, 80, $errno, $errstr, 10 ) or exit ( $errstr . "--->" . $errno );
        $rReferer = '';
        $header = "POST " . '/api/merchant/'.$func.".do" . " HTTP/1.1\r\n";
        $header .= "Host: " . $this->url . "\r\n";
        $header .= "Referer: " . $rReferer . "\r\n";
        $header .= "appkey: " . $this->appkey . "\r\n";
        $header .= "version_no: " . $this->version_no . "\r\n";
        $header .= "Content-Type: application/x-www-form-urlencoded\r\n";
        $header .= "Content-Length: " . $length . "\r\n";
        $header .= "Connection: Close\r\n\r\n";
        $header .= $params . "\r\n";
       
        fputs ( $fp, $header );
        
        $inheader = 1;
        $result = '';
        while ( ! feof ( $fp ) ) {
            $line = fgets ( $fp, 2048 );
            //echo $line;
            if ($inheader && ($line == "\n" || $line == "\r\n")) {
                $inheader = 0;
            }
            
            if ($inheader == 0) {
                $result .= $line;
            }
        }
       
        fclose ( $fp );
        if (array_key_exists ( 'format', $rData ) && $rData ['format'] == 1) {
            $sp_start = '<';
            $sp_end = '>';
        } else {
            $sp_start = '{';
            $sp_end = '}';
        }
        
        $pos = strpos ( $result, $sp_start );
        $result = substr ( $result, $pos, strlen ( $result ) );
        $pos = strrpos ( $result, $sp_end );
        $result = substr ( $result, 0, $pos + 1 );
        
        $result = $this->decodeToArray($result);
        
        return $result;
    }
    
    /**
     * UleAPI::get()
     * 
     * @param mixed $rUrl
     * @return
     */
    public function get($func, $params) {
        $str_params = '';
        foreach ( $params as $k => $v ) {
            $str_params .= "&$k=$v";
        }
        //$str_params = substr($str_params, 1);
        

        $rUrl = 'http://' . $this->url . '/api/merchant/' . $func . '.do?appkey=' . $this->appkey . '&version_no=' . $this->version_no . $str_params;
    
        $result = file_get_contents ( $rUrl );
        
        $result = $this->decodeToArray($result);
        if ($result == null) {
             throw new UleRuntimeExecption(-1, '返回值为空或json解析出错');
        }
        if ($result['returnCode'] != '0000') {
        	throw new UleRuntimeExecption($result['returnCode'], UleRuntimeExecption::getErrorMsg($result['returnCode']));
        }
        
        return $result;
    }
    
    function decodeToArray($str) {
    	return json_decode($str, true);
    }
    
    /**
     * UleAPI::uleEncryption()
     * 
     * @param mixed $rData
     * @return
     */
    public function uleEncryption($rData) {
        $rData = $this->uleRequestSort ( $rData );
        $rData = str_replace ( '=', '', $rData );
        $rData = str_replace ( '&', '', $rData );
        $data = $this->uleHmac ( $rData );
        $data = strtoupper ( $data );
        $data = base64_encode ( $data );
        $data = str_replace ( '\r', '', $data );
        $data = str_replace ( '\n', '', $data );
        $data = urlencode ( $data );
        
        return $data;
    }
    
    /**
     * UleAPI::uleRequestSort()
     * 
     * @param mixed $rRequestArray
     * @return
     */
    private function uleRequestSort($rRequestArray) {
        ksort ( $rRequestArray );
        $request = '';
        foreach ( $rRequestArray as $key => $value ) {
            $request .= '&' . $key . '=' . $value;
        }
        
        $request = substr ( $request, 1 );
        
        return $request;
    }
    
    /**
     * UleAPI::uleHmac()
     * 
     * @param mixed $rData
     * @return
     */
    private function uleHmac($rData) {
        $key = (strlen ( $this->key ) > 64) ? pack ( 'H32', 'md5' ) : str_pad ( $this->key, 64, chr ( 0 ) );
        $ipad = substr ( $key, 0, 64 ) ^ str_repeat ( chr ( 0x36 ), 64 );
        $opad = substr ( $key, 0, 64 ) ^ str_repeat ( chr ( 0x5C ), 64 );
        
        return md5 ( $opad . pack ( 'H32', md5 ( $ipad . $rData ) ) );
    }
}